package ar.edu.caece.pl.asin.model.impl;

import ar.edu.caece.pl.alex.model.IToken;
import ar.edu.caece.pl.alex.model.impl.Token;
import ar.edu.caece.pl.asin.manager.IAnalizadorSintactico;
import ar.edu.caece.pl.asin.manager.impl.AbstractAnalizadorSintactico;
import ar.edu.caece.pl.asin.model.ITokenStream;

public class Sentencia extends AbstractAnalizadorSintactico implements IAnalizadorSintactico {
	
	/* INICIALIZACION */	
	public Sentencia ( ITokenStream ts ) {
		super(ts, false);
	}
	public Sentencia ( ITokenStream ts, boolean debugMode ) {
		super(ts,debugMode);
	}
	
	
	/** 
	 * Devuelve true si reconoce una sentencia individual
	 */
	public boolean reconocer () {

		boolean recognized = true; //(asumimos correctitud hasta demostrar lo contrario)
		
		//----------------------------------------------
		//Agrego info de debug de la produccion
		em.debug( "Reconocer Sentencia:", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
		//----------------------------------------------
		
		/* <SENTENCIA> ->
		  	  IDENTIFICADOR <SENTENCIA_1> ; <SENTENCIA> |
              IF <CONDICION> THEN <SENTENCIA> <ELSE> ENDIF ; <SENTENCIA> |
              WHILE <CONDICION> DO <SENTENCIA> END-WHILE	; <SENTENCIA> |
              SHOWLN <SHOW_ELEM>	; <SENTENCIA> |
              SHOW   <SHOW_ELEM>	; <SENTENCIA> |
              READ   IDENTIFICADOR	; <SENTENCIA> |
              ; <SENTENCIA> |
       		  LAMBDA								*/
		
		if ( this.getTokenSiguiente().getType() == IToken.TYPE_IDENTIFICADOR ) {
			
			// <SENTENCIA> -> IDENTIFICADOR <SENTENCIA_1> ; <SENTENCIA>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA> -> IDENTIFICADOR <SENTENCIA_1> ; <SENTENCIA>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			// Reconocer Identificador
			if ( !this.reconocerToken(IToken.TYPE_IDENTIFICADOR) ) {
				//El reconocerToken() habria adelantado el tokenStream hasta salir de esta iteracion de Sentencia,
				//entonces no hay que seguir buscando sino salir
				return false;
			}
			
			// Reconocer <sentencia1>
			IAnalizadorSintactico sentencia1 = new Sentencia1(this.tokenStream, this.debugMode);
			recognized &= sentencia1.reconocer();
			
			// Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}
			
			//Cierra el bucle de procs funcs o sentencia
			
		} else if ( this.getTokenSiguiente().equals( new Token(IToken.PALABRA_RESERVADA_IF) ) ) {
			
			//<SENTENCIA> -> IF <CONDICION> THEN <SENTENCIA> <ELSE> ENDIF ; <SENTENCIA>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA> -> IF <CONDICION> THEN <SENTENCIA> <ELSE> ENDIF ; <SENTENCIA>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			// Reconocer IF
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_IF) ) {
				return false;
			}
			
			// Reconocer Condicion
			IAnalizadorSintactico condicion = new Condicion(this.tokenStream,this.debugMode);
			recognized &= condicion.reconocer();

			// Reconocer THEN
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_THEN) ) {
				return false;
			}
			
			// Reconocer varias <SENTENCIA>
			while ( Sentencia.primeros( this.getTokenSiguiente() ) ) {
				
				IAnalizadorSintactico sentencia = new Sentencia(this.tokenStream, this.debugMode);
				recognized &= sentencia.reconocer();
			}	
			
			// Reconocer <ELSE>
			IAnalizadorSintactico e = new Else(this.tokenStream, this.debugMode);
			recognized &= e.reconocer();	
			
			// Reconocer ENDIF
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_END_IF) ) {
				return false;
			}
			
			// Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}
			
		} else if ( this.getTokenSiguiente().equals( new Token (IToken.PALABRA_RESERVADA_WHILE) ) ) {
			
			//<SENTENCIA> -> WHILE <EXP> <C'> DO <SENTENCIA> END-WHILE ; <SENTENCIA> 
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA> -> WHILE <EXP> <C'> DO <SENTENCIA> END-WHILE ; <SENTENCIA>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------		
			
			// Reconocer WHILE
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_WHILE) ) {
				return false;
			}
			
			// Reconocer Condicion
			IAnalizadorSintactico condicion = new Condicion(this.tokenStream,this.debugMode);
			recognized &= condicion.reconocer();
			
			// Reconocer DO
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_DO) ) {
				return false;
			}
			
			// Reconocer varias <SENTENCIA>
			while ( Sentencia.primeros( this.getTokenSiguiente() ) ) {
				
				IAnalizadorSintactico sentencia = new Sentencia(this.tokenStream, this.debugMode);
				recognized &= sentencia.reconocer();
			}	
			
			// Reconocer END-WHILE
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_END_WHILE) ) {
				return false;
			}
			
			// Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}
			
		} else if ( this.getTokenSiguiente().equals( new Token (IToken.PALABRA_RESERVADA_SHOWLN ) ) ) {
			
			// <SENTENCIA> -> SHOWLN <SHOW_ELEM>	; <SENTENCIA>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA> -> SHOWLN <SHOW_ELEM> ; <SENTENCIA>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------		
			
			// Reconocer SHOWLN
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_SHOWLN) ) {
				return false;
			}
			
			// Reconocer <SHOWELEM>
			while ( ShowElem.primeros( this.getTokenSiguiente() ) ) {			
				IAnalizadorSintactico showElem = new ShowElem(this.tokenStream, this.debugMode);
				recognized &= showElem.reconocer();	
			}
			
			// Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}
			
		} else if ( this.getTokenSiguiente().equals( new Token (IToken.PALABRA_RESERVADA_SHOW) ) ) {
			
			// <SENTENCIA> -> SHOW   <SHOW_ELEM>	; <SENTENCIA>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA> -> SHOW <SHOW_ELEM> ; <SENTENCIA>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------		
			
			// Reconocer SHOW
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_SHOW) ) {
				return false;
			}
			
			// Reconocer <SHOWELEM>
			while ( ShowElem.primeros( this.getTokenSiguiente() ) ) {			
				IAnalizadorSintactico showElem = new ShowElem(this.tokenStream, this.debugMode);
				recognized &= showElem.reconocer();	
			}	
			
			// Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}


		} else if ( this.getTokenSiguiente().equals( new Token (IToken.PALABRA_RESERVADA_READ) ) ) {
			
			// <SENTENCIA> -> READ   IDENTIFICADOR	; <SENTENCIA>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA> -> READ IDENTIFICADOR ; <SENTENCIA>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------		
			
			// Reconocer READ
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_READ) ) {
				return false;
			}
			
			// Reconocer IDENTIFICADOR
			if ( !this.reconocerToken(IToken.TYPE_IDENTIFICADOR) ) {
				return false;
			}
			
			// Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}
			
		} else if ( this.getTokenSiguiente().equals( new Token (IToken.TYPE_PUNTO_COMA) ) ) {
			
			// <SENTENCIA> -> ; <SENTENCIA>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA> -> ; <SENTENCIA>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------		
			
			// Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}
		
		}
		
		return recognized;
	}
	
	public static boolean primeros(IToken token) {
		return  token.equals( new Token(IToken.TYPE_IDENTIFICADOR) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_IF) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_WHILE) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_SHOWLN) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_SHOW) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_READ) ) ||
				token.equals( new Token(IToken.TYPE_PUNTO_COMA) );
	}
}
